package org.zoomdev.zoom.hash;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class ArrayConsistentHash {
    private final int[] hashRing;    // 排序后的虚拟节点哈希值
    private final String[] nodeNames; // 对应位置的物理节点名称

    public ArrayConsistentHash(List<String> physicalNodes, int virtualNodesPerShard) {
        // 生成虚拟节点哈希值与物理节点映射关系
        List<HashNode> hashNodes = new ArrayList<>();

        for (String node : physicalNodes) {
            for (int i = 0; i < virtualNodesPerShard; i++) {
                String vNode = node + "#VN" + i;
                int hash = hashFunction(vNode);
                hashNodes.add(new HashNode(hash, node));
            }
        }

        // 按哈希值排序
        hashNodes.sort(Comparator.comparingInt(a -> a.hash));

        // 分离哈希值和节点名称
        this.hashRing = new int[hashNodes.size()];
        this.nodeNames = new String[hashNodes.size()];

        for (int i = 0; i < hashNodes.size(); i++) {
            HashNode hn = hashNodes.get(i);
            hashRing[i] = hn.hash;
            nodeNames[i] = hn.node;
        }
    }

    public String getNode(String key) {
        int hash = hashFunction(key);
        int idx = Arrays.binarySearch(hashRing, hash);

        if (idx < 0) {
            idx = -idx - 1;
            if (idx >= hashRing.length) idx = 0;
        }

        return nodeNames[idx];
    }

    private int hashFunction(String key) {
        final int FNV_32_INIT = 0x811c9dc5;
        final int FNV_32_PRIME = 0x01000193;
        int hash = FNV_32_INIT;
        for (byte b : key.getBytes()) {
            hash ^= b;
            hash *= FNV_32_PRIME;
        }
        return hash & 0x7fffffff; // 确保非负数
        // return Hashing.murmur3_32().hashUnencodedChars(key).asInt() & 0x7FFFFFFF;
    }

    private static class HashNode {
        final int hash;
        final String node;

        HashNode(int hash, String node) {
            this.hash = hash;
            this.node = node;
        }
    }

//    private int hashFunction(String key){
//        final int p = 16777619;
//        int hash = (int) 2166136261L;
//        for (int i = 0; i < key.length(); i++)
//            hash = (hash ^ key.charAt(i)) * p;
//        hash += hash << 13;
//        hash ^= hash >> 7;
//        hash += hash << 3;
//        hash ^= hash >> 17;
//        hash += hash << 5;
//
//        // 如果算出来的值为负数则取其绝对值
//        if (hash < 0)
//            hash = Math.abs(hash);
//        return hash;
//    }
}